﻿#pragma once
#include <memory>
#include <wrl/event.h>

#include "D3DX12.h"
#include "UploadBuffer.h"

struct ObjectConstants
{
    DirectX::XMFLOAT4X4 World = MathHelper::Identity4x4();
};

struct PassConstants
{
    DirectX::XMFLOAT4X4 View = MathHelper::Identity4x4();
    DirectX::XMFLOAT4X4 InvView = MathHelper::Identity4x4();
    DirectX::XMFLOAT4X4 Proj = MathHelper::Identity4x4();
    DirectX::XMFLOAT4X4 InvProj = MathHelper::Identity4x4();
    DirectX::XMFLOAT4X4 ViewProj = MathHelper::Identity4x4();
    DirectX::XMFLOAT4X4 InvViewProj = MathHelper::Identity4x4();
    DirectX::XMFLOAT3 EyePosW = { 0.0f, 0.0f, 0.0f };
    float cbPerObjectPad1 = 0.0f;
    DirectX::XMFLOAT2 RenderTargetSize = { 0.0f, 0.0f };
    DirectX::XMFLOAT2 InvRenderTargetSize = { 0.0f, 0.0f };
    float NearZ = 0.0f;
    float FarZ = 0.0f;
    float TotalTime = 0.0f;
    float DeltaTime = 0.0f;
};

struct FVertex
{
    DirectX::XMFLOAT3 Pos;
    DirectX::XMFLOAT4 Color;
};

struct FFrameResource
{
public:
    FFrameResource(ID3D12Device* InDevice, UINT InPassCount, UINT InObjectCount);
    FFrameResource(const FFrameResource&) = delete;
    FFrameResource& operator=(const FFrameResource&) = delete;
    ~FFrameResource();

    // 在GPU处理完与此命令分配器相关的命令之前，我们不能对它进行重置。
    // 所以每一帧都要有它们自己的命令分配器
    Microsoft::WRL::ComPtr<ID3D12CommandAllocator> mCmdListAlloc;

    // 在GPU执行完引用此常量缓冲区的命令之前，我们不能对它进行重置。
    // 因此每一帧都要有它们自己的常量缓冲区
    std::unique_ptr<FUploadBuffer<PassConstants>> mPassCB = nullptr;
    std::unique_ptr<FUploadBuffer<ObjectConstants>> mObjectCB = nullptr;

    // 通过围栏值将命令标记到此围栏点，这使我们可以检测到GPU是否还在使用这些帧资源
    UINT64 mFence = 0;
};
